﻿using Microsoft.AspNet.Authorization;
using Microsoft.AspNet.Hosting;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Mvc;
using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.PlatformAbstractions;
using Microsoft.WindowsAzure.Storage.Blob;
using Newtonsoft.Json;
using Sino.CapacityCloud.Infrastructure.Events;
using Sino.CapacityCloud.Infrastructure.Filters;
using Sino.CapacityCloud.Repositories.Models;
using Sino.CapacityCloud.Services;
using Sino.CapacityCloud.WebApi.ApiControllers;
using Sino.CapacityCloud.WebApi.Utilities;
using Sino.CapacityCloud.WebApi.ViewModels;
using Sino.WebApi.Framework.Core.Filters;
using Sino.WebApi.Framework.Responses;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;

namespace Sino.CapacityCloud.WebApi.ApiControllers
{

    public class EventBusClientController
        : ApiController<EventBusClientController>
    {

        private readonly IEventBus _eventBus;

        public EventBusClientController(
            IHostingEnvironment env,
            IApplicationEnvironment applicationEnvironment,
            IDistributedCache cache,
            ITokenGenertationService tokenGenertationService,
            ApplicationDbContext dbContext,
            ApplicationUserManager userManager,
            ApplicationRoleManager roleManager,
            ApplicationSignInManager signInManager,
            ILoggerFactory loggerFactory,
            IEventBus eventBus)
            : base(env, applicationEnvironment, cache, tokenGenertationService, dbContext, userManager, roleManager, signInManager, loggerFactory)
        {
            this._eventBus = eventBus;
        }

        [SupressUserLogin()]
        [HttpPost]
        public async Task<JsonResult> PostEvent(string typeName)
        {
            try
            {
                this._logger.LogInformation($"Received event data type {typeName}.");
                //var convertedTargetName = $"Sino.CapacityCloud.Services.Models.{typeName}";
                var convertedTargetName = typeName;
                var targetType = EventDataTypeMappings.GetType(convertedTargetName);
                this._logger.LogInformation($"Event data type: {targetType?.AssemblyQualifiedName}.");
                if (targetType != null)
                {
                    using (TextReader tr = new StreamReader(this.HttpContext.Request.Body))
                    {
                        var body = await tr.ReadToEndAsync();
                        this._logger.LogInformation($"Body: \r\n{body}.");
                        this._eventBus.Post(JsonConvert.DeserializeObject(body, targetType), TimeSpan.Zero);
                        return await this.PackageResultAsync(new VoidResponse());
                    }
                }
                else
                {
                    throw new ArgumentException($"The given type {typeName} is not found.");
                }
            }
            catch (Exception ex)
            {
                this._logger.LogError($"Failed to post event data with eventTypeName = {typeName} because: {ex.Message + Environment.NewLine + ex.StackTrace}");
                return await this.PackageResultAsync<AquireStorageSharedSignitureResponse>(ex);
            }
        }

    }

}
